﻿using Newtonsoft.Json;
using TCommon;
using TCommunication.Interface;
using System.Collections.Concurrent;
using TCommunication.Configuration.Interface;
using TCommunication.Configuration.Impl;

namespace TCommunication;
/// <summary>
/// Can盒管理器
/// </summary>
public class CanBoxManager
{
     private static readonly Lazy<CanBoxManager> Instence = new(() => new CanBoxManager());
    /// <summary>
    /// 单例对象
    /// </summary>
    public static CanBoxManager Default => Instence.Value;
    /// <summary>
    /// 配置提供对象字典
    /// </summary>
    private readonly ConcurrentQueue<IConfigProvider> _providers = new();
    /// <summary>
    /// Can盒字典
    /// </summary>
    private readonly ConcurrentDictionary<string, WeakReference<ICanBox>> _canBoxMap = new();
    /// <summary>
    /// 私有构造
    /// </summary>
    private CanBoxManager() { AddDefaultConfig(); }

    /// <summary>
    /// 添加配置提供者
    /// </summary>
    /// <param name="provider"><see cref="IConfigProvider"/>对象</param>
    public void AddConfig(IConfigProvider provider)
    {
        _providers.Enqueue(provider);
    }
    /// <summary>
    /// 获取<see cref="ICanBox"/>对象
    /// </summary>
    /// <param name="canBoxName">can卡名</param>
    /// <returns></returns>
    public OperateResult<ICanBox> GetCommunication(string canBoxName) 
    {
        if (_canBoxMap.TryGetValue(canBoxName, out WeakReference<ICanBox>? weakReference))
        {
            if (weakReference.TryGetTarget(out ICanBox? canBox))
            {
                return OperateResult.CreateSuccessResult(canBox);
            }
            else
            {
                var result = CreateCanBox(canBoxName);
                if (result.IsSuccess)
                {
                    var content = result.Content!;
                    weakReference.SetTarget(content);
                    return OperateResult.CreateSuccessResult(content);
                }
                else
                {
                    return result;
                }
            }
        }
        else
        {
            var result = CreateCanBox(canBoxName);
            if (result.IsSuccess)
            {
                var content = result.Content!;
                var reference = new WeakReference<ICanBox>(content);
                this._canBoxMap.TryAdd(canBoxName, reference);
                return OperateResult.CreateSuccessResult(content);
            }
            else
            {
                return result;
            }
        }
    }
    /// <summary>
    /// 创建连接对象
    /// </summary>
    /// <param name="canBoxName">can卡名</param>
    /// <returns>创建结果</returns>
    private OperateResult<ICanBox> CreateCanBox(string canBoxName)
    {
        foreach (var configProvider in _providers)
        {
            var getConfigResult = configProvider.GetConfigInfo(canBoxName);
            if (getConfigResult.IsSuccess)
            {
                var configInfo = getConfigResult.Content!;
                try
                {
                    if (configInfo.TypeInstance != null)
                    {
                        var o = JsonConvert.DeserializeObject(configInfo.Config ?? string.Empty, configInfo.TypeInstance);
                        if (o is ICanBox canBox)
                        {
                            return OperateResult.CreateSuccessResult(canBox);
                        }
                        else
                        {
                            return OperateResult.CreateFailedResult<ICanBox>(
                                $"无法将类型{configInfo.Type}转换为{nameof(ICanBox)}");
                        }
                    }
                }
                catch (Exception e)
                {
                    return OperateResult.CreateFailedResult<ICanBox>(
                        $"解析配置{canBoxName}时发生异常:{e.Message}\r\n{e.Source}\r\n{e.StackTrace}");
                }
            }
        }

        return OperateResult.CreateFailedResult<ICanBox>($"未定义连接{canBoxName}");
    }
    /// <summary>
    /// 添加默认配置
    /// </summary>
    private void AddDefaultConfig()
    {
        string defaultConfigFile = "./Config/CanBoxSetting.json";
        var fullPath = Path.GetFullPath(defaultConfigFile);
        if (File.Exists(fullPath))
        {
            AddConfig(new JsonFileConfigProvider { FilePath = fullPath });
        }
    }
}